package org.linlinjava.litemall.wx.service;

//import static org.linlinjava.litemall.admin.util.AdminResponseCode.ADMIN_INVALID_ACCOUNT;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.paypal.base.rest.APIContext;
//import org.apache.shiro.authc.AuthenticationException;
//import org.apache.shiro.authc.LockedAccountException;
//import org.apache.shiro.authc.UnknownAccountException;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//import org.linlinjava.litemall.admin.service.LogHelper;
//import org.linlinjava.litemall.admin.util.RandomUtils;
import org.linlinjava.litemall.core.constant.LumiereCloverAPIConstant;
import org.linlinjava.litemall.core.constant.LumiereCloverConstant;
import org.linlinjava.litemall.core.notify.AwsNotifyService;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.payment.DefaultCurType;
import org.linlinjava.litemall.core.payment.PaymentResponseCode;
import org.linlinjava.litemall.core.payment.clover.config.CloverConfig;
import org.linlinjava.litemall.core.payment.clover.dto.ApiChargeDTO;
import org.linlinjava.litemall.core.payment.clover.rq.ApiChargeRQ;
import org.linlinjava.litemall.core.payment.clover.service.GiftCardCloverService;
import org.linlinjava.litemall.core.payment.paypal.service.impl.CardPaypalServiceImpl;
import org.linlinjava.litemall.core.util.AdminCouponDateUtil;
import org.linlinjava.litemall.core.util.GeneratorUtil;
import org.linlinjava.litemall.core.util.RegexUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.bcrypt.BCryptPasswordEncoder;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.dto.CloverChargesDTO;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.linlinjava.litemall.wx.constant.LitemallWXConstants;
import org.linlinjava.litemall.wx.manage.WxGiftCardManageService;
import org.linlinjava.litemall.wx.dto.*;
import org.linlinjava.litemall.wx.util.WxResponseCode;
import org.linlinjava.litemall.wx.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static org.linlinjava.litemall.db.beans.Constants.PAY_TYPE_BALANCE;
import static org.linlinjava.litemall.db.beans.Constants.PAY_TYPE_GIFT_CARD;
import static org.linlinjava.litemall.wx.util.WxResponseCode.*;
import static org.linlinjava.litemall.wx.util.WxResponseCode.AUTH_INVALID_ACCOUNT;

/**
 * @author ：stephen
 * @date ：Created in 2020/4/2 13:48
 * @description：礼物卡服务
 * TODO 第三方付款成功、本地失败处理
 *  暂时的思路是起一个定时任务通过转账id从第三方检查付款状态是否本地余额是否改变成功
 *  目前使用更新时间来作为是否成功修改余额判断
 */
@Slf4j
@Service
public class WxGiftCardService {

    private final Log logger = LogFactory.getLog(WxGiftCardService.class);

    @Autowired
    private LitemallGiftCardService litemallGiftCardService;
    @Autowired
    private LitemallGiftCardUserService litemallGiftCardUserService;
    @Autowired
    private LitemallGiftCardUserLogService litemallGiftCardUserLogService;
    @Autowired
    private LitemallCategoryService categoryService;
    @Autowired
    private LitemallRechargeTransactionsService litemallRechargeTransactionsService;
    @Resource
    private LitemallGiftCardOrderService litemallGiftCardOrderService;
    @Resource
    private LitemallGiftCardShareService litemallGiftCardShareService;
    @Autowired
    private CardPaypalServiceImpl cardPaypalService;
    @Autowired
    private LitemallUserService litemallUserService;
    @Autowired
    private NoticeHelper noticeHelper;
    @Autowired
    private LitemallOrderService orderService;

    @Autowired
    private LitemallRechargeConsumptionService litemallRechargeConsumptionService;

    @Autowired
    private AwsNotifyService awsNotifyService;

    @Autowired
    private LitemallOrderGoodsService orderGoodsService;

    @Autowired
    private WxGiftCardManageService wxGiftCardManageService;

    @Autowired
    private LitemallOrderService litemallOrderService;

    @Autowired
    private GiftCardCloverService giftCardCloverService;

    @Autowired
    private CloverConfig cloverConfig;

    @Autowired
    private LumiereCloverChargesLogService lumiereCloverChargesLogService;


    @Autowired
    private LumiereCouponStrategyService lumiereCouponStrategyService;
    @Autowired
    private LumiereCouponUserService lumiereCouponUserService;


    @Value("${card.paypal.success}")
    private String successUrl;
    @Value("${card.paypal.cancel}")
    private String cancelUrl;

    /**
     * 查询所有可购买的礼物卡，
     * 根据category_ids 分类
     * 没有的则认为是通用的(返回值type=0)
     * 其他的则会按照商品分类去查询type和name，理论上添加礼物卡时只能指定一个父级类目下的子类，这里不做判断，仅查询第一个category_id的父级作为他的分组依据
     * @return
     */
    public Object all(Integer userId) {

        List<LitemallGiftCard> cards = litemallGiftCardService.list(Wrappers.lambdaQuery(LitemallGiftCard.class)
                .eq(LitemallGiftCard::getStatus,1)
                .eq(LitemallGiftCard::getType,1));

        List<LitemallGiftCardVo> vos = new ArrayList<>();
        vos = cards.stream().map(card -> {
            LitemallGiftCardVo vo = new LitemallGiftCardVo();
            BeanUtils.copyProperties(card,vo);
            List<LitemallGiftCardUser> users =  litemallGiftCardUserService.selectByCardId(card.getId(),userId);
            if(users.size() > 0){
                vo.setGiftCardUserId(users.get(0).getId());
                vo.setIsUserHave(true);
            }else{
                vo.setIsUserHave(false);
            }
            return vo;
        }).collect(Collectors.toList());

        return ResponseUtil.ok(vos);
    }

    /**
     * 购买礼物卡
     *
     * @param cardId      卡id
     * @param amount      量
     * @param shopId      商店id
     * @return {@link Object}
     */
    @Transactional
    public Object buyCard(Integer userId,Integer cardId,BigDecimal amount,Integer shopId) {
        LitemallGiftCard card = litemallGiftCardService.findById(cardId);
        if(card == null){
            return ResponseUtil.fail(CARD_INVALID, "礼物卡不存在");
        }

        // 校验礼物卡可购买数量
        Integer saleNum =  (int) litemallGiftCardUserService.sumByCardId(cardId);
        if(card.getNumbers() != 0 && saleNum >= card.getNumbers()){
            return ResponseUtil.fail(CARD_SALED_OVER,"礼物卡已售罄");
        }

        //创建一个礼物卡的订单
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setAmount(amount);
//        order.setCardNumber(RandomUtils.generateRandomStr(10));
        order.setGiftCardId(card.getId());
        order.setUserId(userId);
        order.setPayType(Constants.PAY_TYPE_PAYPAL);
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setShopId(shopId);
        order.setAddUserId(userId);
        order.setPayStatus(Constants.PAY_STATUS_DOING);
        litemallGiftCardOrderService.add(order);
        return ResponseUtil.ok(order);
    }


    /**
     * 余额购买礼物卡  （自己给自己购买）
     *
     * @param userId          用户id
     * @param moneyBuyCardDto 钱买卡dto
     * @return {@link ResponseUtil.Response}
     */
    @Transactional
    public ResponseUtil.Response moneyBuyCard(Integer userId, MoneyBuyCardDTO moneyBuyCardDto) {
        //用户登录判断
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        LitemallUser user = litemallUserService.findById(userId);

        //判断购买的礼物卡效果
        LitemallGiftCard card = litemallGiftCardService.findById(moneyBuyCardDto.getBuyCardId());
        if(card == null){
            return ResponseUtil.fail(CARD_INVALID, "礼物卡不存在");
        }
        //查用户余额
        if(user.getAvailableAmount().compareTo(moneyBuyCardDto.getAmount())==-1){
            return ResponseUtil.fail(MONEY_BUY_PAY_INSUFFICIENT,"用户余额不足");
        }
        //扣除支付礼物卡余额
        user.setAvailableAmount(user.getAvailableAmount().subtract(moneyBuyCardDto.getAmount()));
        if(litemallUserService.updateById2(user)==0){
            return ResponseUtil.fail(MONEY_DEDUCT_FAILURE,"余额扣除失败！");
        }

        //创建礼物卡订单
        String cardNumber = RandomUtil.randomNumbers(16);
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setGiftCardId(card.getId());
        order.setCardNumber(cardNumber);
        order.setUserId(userId);
        order.setPayType((byte) 3);
        order.setPayStatus((byte) 2);
        order.setPayTime(LocalDateTime.now());
        order.setAmount(moneyBuyCardDto.getAmount());
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setShopId(moneyBuyCardDto.getShopId());
        order.setAddUserId(userId);
        order.setAddUserName(user.getUsername());
        litemallGiftCardOrderService.add(order);


        //创建充值消费订单
        LitemallRechargeConsumption rechargeConsumption = new LitemallRechargeConsumption();
        rechargeConsumption.setUserId(user.getId());
        rechargeConsumption.setOrderId(order.getId());
        rechargeConsumption.setMobile(StrUtil.isNotEmpty(user.getMobile())?user.getMobile():null);
        rechargeConsumption.setUsername(user.getUsername());
        rechargeConsumption.setUserLevel(user.getUserLevel());
        rechargeConsumption.setAvailableAmount(user.getAvailableAmount());
        rechargeConsumption.setPoints(user.getPoints());
        rechargeConsumption.setType((byte) 2);
        rechargeConsumption.setAmount(moneyBuyCardDto.getAmount());
        rechargeConsumption.setDeleted(false);
        rechargeConsumption.setAddUserId(userId);
        rechargeConsumption.setOrderSource((byte) 1);
        litemallRechargeConsumptionService.add(rechargeConsumption);

        //创建新的用户礼物卡
        LitemallGiftCardUser createCardUser = new LitemallGiftCardUser();
        createCardUser.setCardNumber(cardNumber);
        createCardUser.setEntityCardCode(card.getType()==2?createCardUser.getCardNumber():null);
        createCardUser.setUserId(userId);
        createCardUser.setUserName(litemallUserService.findById(userId).getUsername());
        createCardUser.setGiftCardId(card.getId());
        createCardUser.setAmount(moneyBuyCardDto.getAmount());
        createCardUser.setStatus(0);
        createCardUser.setDeleted(false);
        //createCardUser.setShopId(moneyBuyCardDto.getShopId());
        createCardUser.setIsDefault(0);
        litemallGiftCardUserService.add(createCardUser);

        //创建用户使用礼物卡日志
        LitemallGiftCardUserLog log =new LitemallGiftCardUserLog();
        log.setCardNumber(cardNumber);
        log.setType((byte) 1);
        log.setAmount(moneyBuyCardDto.getAmount());
        log.setAddUserId(userId);
        log.setContent("Balance Purchase Gift Card (Buy for Yourself)");
        log.setOrderId(order.getId());
        log.setCardUserId(createCardUser.getId());
        log.setBalance(createCardUser.getAmount());
        //log.setShopId(moneyBuyCardDto.getShopId());
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        log.setAddUserName(user.getUsername());
        log.setChangePoints(BigDecimal.ZERO);
        litemallGiftCardUserLogService.add(log);


        //发送系统通知
        String zcontent = "Congratulations, you got the " + card.getName();
        noticeHelper.noticeUser( Constants.MSG_TYPE_OTHER,"Gift card recharge", zcontent, userId,card);
        return ResponseUtil.ok(createCardUser);
    }

    /**
     * 余额购买礼物卡赠送
     *
     * @param userId               用户id
     * @param moneyBuyGiveeCardDto 钱买givee卡dto
     * @return {@link ResponseUtil.Response}
     */
    @Transactional
    public ResponseUtil.Response moneyBuyGiveeCard(Integer userId, MoneyBuyGiveeCardDTO moneyBuyGiveeCardDto) {
        //用户登录判断
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        //被赠送用户
        LitemallUser giveeUser = litemallUserService.queryMobileOrEmail(moneyBuyGiveeCardDto.getGivee());

        if (!RegexUtil.isMobileValid(moneyBuyGiveeCardDto.getGivee()) && !RegexUtil.isEmailExact(moneyBuyGiveeCardDto.getGivee())) {
            return ResponseUtil.fail(AUTH_INVALID_MOBILE, "手机号或邮箱格式不正确");
        }
        LitemallUser user = litemallUserService.findById(userId);
        //判断购买的礼物卡效果
        LitemallGiftCard card = litemallGiftCardService.findById(moneyBuyGiveeCardDto.getBuyCardID());
        if(card == null){
            return ResponseUtil.fail(CARD_INVALID, "礼物卡不存在");
        }
        // 校验礼物卡可购买数量
        Integer saleNum =  (int) litemallGiftCardUserService.sumByCardId(card.getId());
        if(card.getNumbers() != 0 && saleNum >= card.getNumbers()){
            return ResponseUtil.fail(CARD_SALED_OVER,"礼物卡已售罄");
        }
        //查用户余额
        if(user.getAvailableAmount().compareTo(moneyBuyGiveeCardDto.getAmount())==-1){
            return ResponseUtil.fail(MONEY_BUY_PAY_INSUFFICIENT,"用户余额不足");
        }
        //扣除用户余额
        user.setAvailableAmount(user.getAvailableAmount().subtract(moneyBuyGiveeCardDto.getAmount()));
        if(litemallUserService.updateById2(user)==0){
            return ResponseUtil.fail(MONEY_DEDUCT_FAILURE,"余额扣除失败！");
        }
        //TODO 与礼物卡赠送重复  可以优化
        String cardNumber = RandomUtil.randomNumbers(16);
        //创建礼物卡订单
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setGiftCardId(card.getId());
        order.setCardNumber(cardNumber);
        order.setUserId(userId);
        order.setPayStatus((byte) 2);
        order.setPayTime(LocalDateTime.now());
        order.setAmount(moneyBuyGiveeCardDto.getAmount());
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setShopId(moneyBuyGiveeCardDto.getShopId());
        order.setPayType(PAY_TYPE_BALANCE);
        order.setMessage(moneyBuyGiveeCardDto.getMessage());

        //创建新的用户礼物卡
        LitemallGiftCardUser createCardUser = new LitemallGiftCardUser();
        createCardUser.setCardNumber(cardNumber);
        createCardUser.setEntityCardCode(card.getType()==2?createCardUser.getCardNumber():null);
        createCardUser.setUserId(ObjectUtil.isNotEmpty(giveeUser)?giveeUser.getId():null);
        createCardUser.setUserName(ObjectUtil.isNotEmpty(giveeUser)?giveeUser.getUsername():moneyBuyGiveeCardDto.getGivee());
        createCardUser.setGiftCardId(card.getId());
        createCardUser.setAmount(moneyBuyGiveeCardDto.getAmount());
        createCardUser.setStatus(0);
        createCardUser.setDeleted(false);
        createCardUser.setShopId(moneyBuyGiveeCardDto.getShopId());
        createCardUser.setIsDefault(0);
        litemallGiftCardUserService.add(createCardUser);

        LitemallGiftCardUserLog log =new LitemallGiftCardUserLog();
        log.setCardNumber(cardNumber);
        log.setType(Constants.LOG_GIFTCARD_SHARE);
        log.setAmount(moneyBuyGiveeCardDto.getAmount());
        log.setAddUserId(userId);
        log.setContent("Gift card with balance purchase");
        log.setOrderId(order.getId());
        log.setCardUserId(createCardUser.getUserId());
        log.setBalance(createCardUser.getAmount());
        //log.setShopId(moneyBuyGiveeCardDto.getShopId());
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        log.setAddUserName(user.getUsername());
        log.setChangePoints(BigDecimal.ZERO);
        litemallGiftCardUserLogService.add(log);


        //赠送用户
        LitemallUser payUser = litemallUserService.findById(userId);
        //分 被赠送用户是否是注册用户
        if(ObjectUtil.isNotEmpty(giveeUser)){
            //用户存在  添加礼物卡购买订单
            order.setAddUserId(giveeUser.getId());
            order.setAddUserName(giveeUser.getUsername());
            litemallGiftCardOrderService.add(order);
            //发送通知信息   给赠送者发送系统通知   被赠送者发送邮箱、短信、系统通知
            wxGiftCardManageService.sendNotificationToExistUser(card,payUser,giveeUser,order,createCardUser,moneyBuyGiveeCardDto.getMessage());
            //记录日志 1礼物卡订单卡号 4用户礼物卡用户ID 5订单金额 6礼物卡订单ID 7用户礼物卡金额 8礼物卡订单ID
            log(order.getCardNumber(), Constants.LOG_GIFTCARD_PICK, "余额购买礼物卡赠送",createCardUser.getId(),order.getAmount(),card.getId(),createCardUser.getAmount(),order.getId());
        }else {
            //用户不存在  添加礼物卡购买订单
            order.setAddUserId(null);
            order.setAddUserName(moneyBuyGiveeCardDto.getGivee());
            litemallGiftCardOrderService.add(order);
            //发送通知信息   给赠送者发送系统通知   被赠送者发送邮箱或短信
            wxGiftCardManageService.sendNotificationToNotExistUser(card,order,createCardUser,payUser,moneyBuyGiveeCardDto.getGivee(),moneyBuyGiveeCardDto.getMessage());
            //记录日志 1礼物卡订单卡号 4用户礼物卡用户ID 5订单金额 6礼物卡订单ID 7用户礼物卡金额 8礼物卡订单ID
            log(order.getCardNumber(), Constants.LOG_GIFTCARD_PICK, "余额购买礼物卡赠送",createCardUser.getId(),order.getAmount(),card.getId(),createCardUser.getAmount(),order.getId());
        }
        return ResponseUtil.ok(createCardUser);
    }

    /**
     * 礼物卡购买礼物卡 （自己给自己购买）
     *
     * @param userId         用户id
     * @param cardBuyCardDto 卡买卡dto
     * @return {@link ResponseUtil.Response}
     */
    @Transactional
    public ResponseUtil.Response cardBuyCard(Integer userId, CardBuyCardDTO cardBuyCardDto) {
        //用户登录判断
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        LitemallUser user = litemallUserService.findById(userId);

        //判断购买的礼物卡效果
        LitemallGiftCard card = litemallGiftCardService.findById(cardBuyCardDto.getBuyCardId());
        if(card == null){
            return ResponseUtil.fail(CARD_INVALID, "礼物卡不存在");
        }
        // 校验礼物卡可购买数量
        Integer saleNum =  (int) litemallGiftCardUserService.sumByCardId(card.getId());
        if(card.getNumbers() != 0 && saleNum >= card.getNumbers()){
            return ResponseUtil.fail(CARD_SALED_OVER,"礼物卡已售罄");
        }
        //创建礼物卡订单
        String cardNumber = RandomUtil.randomNumbers(16);
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setGiftCardId(card.getId());
        order.setCardNumber(cardNumber);
        order.setUserId(userId);
        order.setPayType(PAY_TYPE_GIFT_CARD);
        order.setPayStatus((byte) 2);
        order.setPayTime(LocalDateTime.now());
        order.setAmount(cardBuyCardDto.getAmount());
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setShopId(cardBuyCardDto.getShopId());
        order.setAddUserId(userId);
        order.setAddUserName(user.getUsername());
        litemallGiftCardOrderService.add(order);

        //查pay礼物卡余额
        LitemallGiftCardUser payCard = litemallGiftCardUserService.getOne(Wrappers.lambdaQuery(LitemallGiftCardUser.class)
                .eq(LitemallGiftCardUser::getUserId,userId)
                .eq(LitemallGiftCardUser::getCardNumber,cardBuyCardDto.getPayCardNumber()));
        if(payCard.getAmount().compareTo(cardBuyCardDto.getAmount())==-1){
            return ResponseUtil.fail(CARD_MONEY_INSUFFICIENT,"用户礼物余额不足");
        }
        //扣除支付礼物卡余额
        payCard.setAmount(payCard.getAmount().subtract(cardBuyCardDto.getAmount()));
        if(litemallGiftCardUserService.updateById2(payCard)==0){
            return ResponseUtil.fail(MONEY_DEDUCT_FAILURE,"余额扣除失败！");
        }

        //创建新的用户礼物卡
        LitemallGiftCardUser createCardUser = new LitemallGiftCardUser();
        createCardUser.setCardNumber(cardNumber);
        createCardUser.setEntityCardCode(card.getType()==2?createCardUser.getCardNumber():null);
        createCardUser.setUserId(userId);
        createCardUser.setUserName(litemallUserService.findById(userId).getUsername());
        createCardUser.setGiftCardId(card.getId());
        createCardUser.setAmount(cardBuyCardDto.getAmount());
        createCardUser.setStatus(0);
        createCardUser.setDeleted(false);
        //createCardUser.setShopId(cardBuyCardDto.getShopId());
        createCardUser.setIsDefault(0);
        litemallGiftCardUserService.add(createCardUser);

        LitemallGiftCardUserLog log =new LitemallGiftCardUserLog();
        log.setCardNumber(cardNumber);
        log.setType((byte) 1);
        log.setAmount(cardBuyCardDto.getAmount());
        log.setAddUserId(userId);
        log.setContent("Gift Card Buying Gift Cards");
        log.setOrderId(order.getId());
        log.setCardUserId(createCardUser.getId());
        log.setBalance(cardBuyCardDto.getAmount());
        //log.setShopId(cardBuyCardDto.getShopId());
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        log.setAddUserName(user.getUsername());
        log.setChangePoints(BigDecimal.ZERO);
        litemallGiftCardUserLogService.add(log);

        LitemallGiftCardUserLog paylog =new LitemallGiftCardUserLog();
        paylog.setCardNumber(cardNumber);
        paylog.setType((byte) 2);
        paylog.setAmount(cardBuyCardDto.getAmount());
        paylog.setAddUserId(payCard.getUserId());
        paylog.setContent("Gift Card Buying Gift Cards");
        paylog.setOrderId(order.getId());
        paylog.setCardUserId(payCard.getId());
        paylog.setBalance(cardBuyCardDto.getAmount());
        //paylog.setShopId(cardBuyCardDto.getShopId());
        paylog.setOrderSource(Constants.ORDER_SOURCE_APP);
        paylog.setAddUserName(user.getUsername());
        litemallGiftCardUserLogService.add(paylog);

        //添加优惠券
        List<LumiereCouponStrategy> couponStrategies = lumiereCouponStrategyService.list(Wrappers.lambdaQuery(LumiereCouponStrategy.class)
                .eq(LumiereCouponStrategy::getCouponType,8)
                .eq(LumiereCouponStrategy::getStatus, 1)
                .le(LumiereCouponStrategy::getRechargeAmount,cardBuyCardDto.getAmount()));
        if(couponStrategies!=null&&couponStrategies.size()>0) {
            for (LumiereCouponStrategy lumiereCouponStrategy : couponStrategies) {
                long nextId = IdUtil.getSnowflake(2, 2).nextId();
                LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(lumiereCouponStrategy);
                //发放券
                for (int i = 1;i<=lumiereCouponStrategy.getTotal();i++){
                    LumiereCouponUser coupon = LumiereCouponUser.builder()
                            .userId(userId)
                            .strategyId(lumiereCouponStrategy.getId())
                            .couponId(lumiereCouponStrategy.getCouponId())
                            .userName(user.getUsername())
                            .startTime(localDateTimes[0])
                            .endTime(localDateTimes[1])
                            .code(String.valueOf(nextId))
                            .addTime(LocalDateTime.now())
                            .updateTime(LocalDateTime.now())
                            .deleted(false)
                            .build();
                    lumiereCouponUserService.save(coupon);
                }
            }
        }

        //发送系统通知
        String zcontent = "Congratulations, you got the " + card.getName();
        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"Gift card recharge", zcontent, userId,card);
        return ResponseUtil.ok(createCardUser);
    }

    @SneakyThrows
    @Transactional
    public ResponseUtil.Response cardBuyClover(Integer shopId, Integer userId, Integer buyCardId, String token, BigDecimal amount) {
        //用户登录判断
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        LitemallUser user = litemallUserService.findById(userId);

        //判断购买的礼物卡效果
        LitemallGiftCard card = litemallGiftCardService.findById(buyCardId);
        if(card == null){
            return ResponseUtil.fail(CARD_INVALID, "礼物卡不存在");
        }
        //判断金额
        if(amount == null||amount.compareTo(new BigDecimal(0.00))<0){
            return ResponseUtil.badArgument();
        }
        // 校验礼物卡可购买数量
        Integer saleNum =  (int) litemallGiftCardUserService.sumByCardId(card.getId());
        if(card.getNumbers() != 0 && saleNum >= card.getNumbers()){
            return ResponseUtil.fail(CARD_SALED_OVER,"礼物卡已售罄");
        }
        //执行支付
        //支付体
        ApiChargeRQ apiChargeRQ = new ApiChargeRQ();
        apiChargeRQ.setAmount(amount.multiply(new BigDecimal(100)));
        apiChargeRQ.setCurrency(DefaultCurType.CAD.getType());
        apiChargeRQ.setSource(token);
        apiChargeRQ.setStored_credentials(new ApiChargeDTO("SUBSEQUENT",true,"CARDHOLDER"));
        //apiChargeRQ.setSource(cloverCard.getCustomerId());
        //开始交易
        OkHttpClient client = new OkHttpClient();

        MediaType mediaType = MediaType.parse(LumiereCloverConstant.APPLICATIONJSON);
        RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(apiChargeRQ));
        Request request = new Request.Builder()
                .url(LumiereCloverAPIConstant.CLOVER_EXECUTEPAYMENT)
                .post(body)
                .addHeader(LumiereCloverConstant.ACCEPT, LumiereCloverConstant.APPLICATIONJSON)
                .addHeader(LumiereCloverConstant.CONTENTTYPE, LumiereCloverConstant.APPLICATIONJSON)
                .addHeader(LumiereCloverConstant.IDEMPOTENCYKEY, IdUtil.simpleUUID())
                .addHeader(LumiereCloverConstant.AUTHORIZATION, String.format(LumiereCloverConstant.BEARER,cloverConfig.getAccessToken()))
                .build();

        Response response = client.newCall(request).execute();
        JSONObject vo =  JSON.parseObject(response.body().string());
        CloverChargesDTO cloverChargesDTO = JSON.toJavaObject(vo,CloverChargesDTO.class);
        //支付失败
        if(StrUtil.isBlank(cloverChargesDTO.getId())){
            log.info("clover card executePayment error : " + vo);
            String resultCode = StrUtil.sub(vo.getString("message"), 0, 3);
            return ResponseUtil.fail(Integer.parseInt(resultCode),vo.getString("error"));
        }


        //创建礼物卡订单
        String cardNumber = RandomUtil.randomNumbers(16);
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setGiftCardId(card.getId());
        order.setCardNumber(cardNumber);
        order.setUserId(userId);
        order.setPayType((byte) 3);
        order.setPayStatus((byte) 2);
        order.setPayTime(LocalDateTime.now());
        order.setAmount(amount);
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setShopId(shopId);
        order.setAddUserId(userId);
        order.setAddUserName(user.getUsername());
        litemallGiftCardOrderService.add(order);
        //创建新的用户礼物卡
        LitemallGiftCardUser createCardUser = new LitemallGiftCardUser();
        createCardUser.setCardNumber(cardNumber);
        createCardUser.setEntityCardCode(card.getType()==2?createCardUser.getCardNumber():null);
        createCardUser.setUserId(userId);
        createCardUser.setUserName(litemallUserService.findById(userId).getUsername());
        createCardUser.setGiftCardId(card.getId());
        createCardUser.setAmount(amount);
        createCardUser.setStatus(0);
        createCardUser.setDeleted(false);
        //createCardUser.setShopId(shopId);
        createCardUser.setIsDefault(0);
        litemallGiftCardUserService.add(createCardUser);


        long chargesLogId = IdUtil.createSnowflake(1, 1).nextId();
        //保存交易记录
        LumiereCloverChargesLog lumiereCloverChargesLog = LumiereCloverChargesLog.builder()
                .id(chargesLogId)
                .userId(userId)
                .shopId(shopId)
                .transactionId(cloverChargesDTO.getId())
                .amount(cloverChargesDTO.getAmount())
                .amountRefunded(cloverChargesDTO.getAmount_refunded())
                .currency(cloverChargesDTO.getCurrency())
                .created(cloverChargesDTO.getCreated())
                .captured(cloverChargesDTO.getCaptured())
                .refNum(cloverChargesDTO.getRef_num())
                .authCode(cloverChargesDTO.getAuth_code())
                .networkStatus(cloverChargesDTO.getOutcome().getNetwork_status())
                .type(cloverChargesDTO.getOutcome().getType())
                .paid(cloverChargesDTO.getPaid())
                .status(cloverChargesDTO.getStatus())
                .customerId(cloverChargesDTO.getSource().getId())
                .addressLine1(cloverChargesDTO.getSource().getAddress_line1())
                .addressLine1Check(cloverChargesDTO.getSource().getAddress_line1_check())
                .addressZip(cloverChargesDTO.getSource().getAddress_zip())
                .addressZipCheck(cloverChargesDTO.getSource().getAddress_zip_check())
                .brand(cloverChargesDTO.getSource().getBrand())
                .expMonth(cloverChargesDTO.getSource().getExp_month())
                .expYear(cloverChargesDTO.getSource().getExp_year())
                .first6(cloverChargesDTO.getSource().getFirst6())
                .last4(cloverChargesDTO.getSource().getLast4())
                .giftCardOrderId(order.getId())
                .transactionType(2)
                .addTime(LocalDateTime.now())
                .deleted(false)
                .build();
        lumiereCloverChargesLogService.save(lumiereCloverChargesLog);
        //发送系统通知
        String zcontent = "You have received a new gift card [ %s ]. Check the card package for details";
        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"Congratulations on a new gift card", String.format(zcontent,card.getCardNo()), userId,card);
        //记录日志 1礼物卡订单卡号 4用户礼物卡用户ID 5订单金额 6礼物卡订单ID 7用户礼物卡金额 8礼物卡订单ID
        log(order.getCardNumber(), Constants.LOG_GIFTCARD_RECHARGE, "Buy your own gift cards",createCardUser.getId(),order.getAmount(),card.getId(),createCardUser.getAmount(),order.getId());
        return ResponseUtil.ok(createCardUser);
    }
    /**
     * 礼物卡买礼物卡赠送
     *
     * @param userId              用户id
     * @param cardBuyGiveeCardDto 礼物卡买礼物卡赠送dto
     * @return {@link ResponseUtil.Response}
     */
    @Transactional
    public ResponseUtil.Response cardBuyGiveeCard(Integer userId, CardBuyGiveeCardDTO cardBuyGiveeCardDto) {
        //用户登录判断
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        LitemallUser litemallUser = litemallUserService.findById(userId);
        //被赠送用户
        LitemallUser giveeUser = litemallUserService.queryMobileOrEmail(cardBuyGiveeCardDto.getGiveeUser());

        if (!RegexUtil.isMobileValid(cardBuyGiveeCardDto.getGiveeUser()) && !RegexUtil.isEmailExact(cardBuyGiveeCardDto.getGiveeUser())) {
            return ResponseUtil.fail(AUTH_INVALID_MOBILE, "手机号或邮箱格式不正确");
        }
        //判断购买的礼物卡效果
        LitemallGiftCard card = litemallGiftCardService.findById(cardBuyGiveeCardDto.getBuyCardId());
        if(card == null){
            return ResponseUtil.fail(CARD_INVALID, "礼物卡不存在");
        }
        // 校验礼物卡可购买数量
        Integer saleNum =  (int) litemallGiftCardUserService.sumByCardId(card.getId());
        if(card.getNumbers() != 0 && saleNum >= card.getNumbers()){
            return ResponseUtil.fail(CARD_SALED_OVER,"礼物卡已售罄");
        }
        //创建礼物卡订单
        String cardNumber = RandomUtil.randomNumbers(16);
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setGiftCardId(card.getId());
        order.setCardNumber(cardNumber);
        order.setUserId(userId);
        order.setPayType((byte) 3);
        order.setPayStatus((byte) 2);
        order.setPayTime(LocalDateTime.now());
        order.setAmount(cardBuyGiveeCardDto.getAmount());
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setShopId(cardBuyGiveeCardDto.getShopId());

        //查pay礼物卡余额
        LitemallGiftCardUser payCard = litemallGiftCardUserService.getOne(Wrappers.lambdaQuery(LitemallGiftCardUser.class)
                .eq(LitemallGiftCardUser::getUserId,userId)
                .eq(LitemallGiftCardUser::getCardNumber,cardBuyGiveeCardDto.getPayCardNumber()));
        if(payCard.getAmount().compareTo(cardBuyGiveeCardDto.getAmount())==-1){
            return ResponseUtil.fail(CARD_MONEY_INSUFFICIENT,"用户礼物余额不足");
        }
        //扣除支付礼物卡余额
        payCard.setAmount(payCard.getAmount().subtract(cardBuyGiveeCardDto.getAmount()));
        if(litemallGiftCardUserService.updateById2(payCard)==0){
            return ResponseUtil.fail(MONEY_DEDUCT_FAILURE,"余额扣除失败！");
        }

        //创建新的用户礼物卡
        LitemallGiftCardUser createCardUser = new LitemallGiftCardUser();
        createCardUser.setCardNumber(cardNumber);
        createCardUser.setEntityCardCode(card.getType()==2?createCardUser.getCardNumber():null);
        createCardUser.setUserId(ObjectUtil.isNotEmpty(giveeUser)?giveeUser.getId():null);
        createCardUser.setUserName(ObjectUtil.isNotEmpty(giveeUser)?giveeUser.getUsername():cardBuyGiveeCardDto.getGiveeUser());
        createCardUser.setGiftCardId(card.getId());
        createCardUser.setAmount(cardBuyGiveeCardDto.getAmount());
        createCardUser.setStatus(0);
        createCardUser.setDeleted(false);
        createCardUser.setShopId(cardBuyGiveeCardDto.getShopId());
        createCardUser.setIsDefault(0);
        litemallGiftCardUserService.add(createCardUser);

        LitemallGiftCardUserLog log =new LitemallGiftCardUserLog();
        log.setCardNumber(cardNumber);
        log.setType(Constants.LOG_GIFTCARD_SHARE);
        log.setAmount(cardBuyGiveeCardDto.getAmount());
        log.setAddUserId(userId);
        log.setContent("Gift cards Buy gift cards give");
        log.setOrderId(order.getId());
        log.setCardUserId(createCardUser.getUserId());
        log.setBalance(createCardUser.getAmount());
        //log.setShopId(cardBuyGiveeCardDto.getShopId());
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        log.setAddUserName(litemallUser.getUsername());
        log.setChangePoints(BigDecimal.ZERO);
        litemallGiftCardUserLogService.add(log);

        //赠送用户
        LitemallUser payUser = litemallUserService.findById(userId);
        //分 被赠送用户是否是注册用户
        if(ObjectUtil.isNotEmpty(giveeUser)){
            //用户存在  添加礼物卡购买订单
            order.setAddUserId(giveeUser.getId());
            order.setAddUserName(giveeUser.getUsername());
            litemallGiftCardOrderService.add(order);
            //发送通知信息   给赠送者发送系统通知   被赠送者发送邮箱、短信、系统通知
            wxGiftCardManageService.sendNotificationToExistUser(card,payUser,giveeUser,order,createCardUser,cardBuyGiveeCardDto.getMessage());
            //记录日志 1礼物卡订单卡号 4用户礼物卡用户ID 5订单金额 6礼物卡订单ID 7用户礼物卡金额 8礼物卡订单ID
            log(order.getCardNumber(), Constants.LOG_GIFTCARD_PICK, "Gift cards Buy gift cards give",createCardUser.getId(),order.getAmount(),card.getId(),createCardUser.getAmount(),order.getId());
        }else {
            //用户不存在  添加礼物卡购买订单
            order.setAddUserId(null);
            order.setAddUserName(cardBuyGiveeCardDto.getGiveeUser());
            litemallGiftCardOrderService.add(order);
            //发送通知信息   给赠送者发送系统通知   被赠送者发送邮箱或短信
            wxGiftCardManageService.sendNotificationToNotExistUser(card,order,createCardUser,payUser,cardBuyGiveeCardDto.getGiveeUser(),cardBuyGiveeCardDto.getMessage());
            //记录日志 1礼物卡订单卡号 4用户礼物卡用户ID 5订单金额 6礼物卡订单ID 7用户礼物卡金额 8礼物卡订单ID
            log(order.getCardNumber(), Constants.LOG_GIFTCARD_PICK, "Gift cards Buy gift cards give",createCardUser.getId(),order.getAmount(),card.getId(),createCardUser.getAmount(),order.getId());
        }
        return ResponseUtil.ok(createCardUser);
    }

    @SneakyThrows
    @Transactional
    public ResponseUtil.Response cardBuyCloverGivee(Integer userId, CardBuyCloverGiveeDTO cardBuyCloverGiveeDTO) {
        //用户登录判断
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        LitemallUser litemallUser = litemallUserService.findById(userId);
        //被赠送用户
        LitemallUser giveeUser = litemallUserService.queryMobileOrEmail(cardBuyCloverGiveeDTO.getGiveeUser());

        if (!RegexUtil.isMobileValid(cardBuyCloverGiveeDTO.getGiveeUser()) && !RegexUtil.isEmailExact(cardBuyCloverGiveeDTO.getGiveeUser())) {
            return ResponseUtil.fail(AUTH_INVALID_MOBILE, "手机号或邮箱格式不正确");
        }
        //判断购买的礼物卡效果
        LitemallGiftCard card = litemallGiftCardService.findById(cardBuyCloverGiveeDTO.getBuyCardId());
        if(card == null){
            return ResponseUtil.fail(CARD_INVALID, "礼物卡不存在");
        }
        // 校验礼物卡可购买数量
        Integer saleNum =  (int) litemallGiftCardUserService.sumByCardId(card.getId());
        if(card.getNumbers() != 0 && saleNum >= card.getNumbers()){
            return ResponseUtil.fail(CARD_SALED_OVER,"礼物卡已售罄");
        }
        //执行支付
        //支付体
        ApiChargeRQ apiChargeRQ = new ApiChargeRQ();
        apiChargeRQ.setAmount(cardBuyCloverGiveeDTO.getAmount().multiply(new BigDecimal(100)));
        apiChargeRQ.setCurrency(DefaultCurType.CAD.getType());
        apiChargeRQ.setSource(cardBuyCloverGiveeDTO.getToken());
        apiChargeRQ.setStored_credentials(new ApiChargeDTO("SUBSEQUENT",true,"CARDHOLDER"));
        //apiChargeRQ.setSource(cloverCard.getCustomerId());
        //开始交易
        OkHttpClient client = new OkHttpClient();

        MediaType mediaType = MediaType.parse(LumiereCloverConstant.APPLICATIONJSON);
        RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(apiChargeRQ));
        Request request = new Request.Builder()
                .url(LumiereCloverAPIConstant.CLOVER_EXECUTEPAYMENT)
                .post(body)
                .addHeader(LumiereCloverConstant.ACCEPT, LumiereCloverConstant.APPLICATIONJSON)
                .addHeader(LumiereCloverConstant.CONTENTTYPE, LumiereCloverConstant.APPLICATIONJSON)
                .addHeader(LumiereCloverConstant.IDEMPOTENCYKEY, IdUtil.simpleUUID())
                .addHeader(LumiereCloverConstant.AUTHORIZATION, String.format(LumiereCloverConstant.BEARER,cloverConfig.getAccessToken()))
                .build();

        Response response = client.newCall(request).execute();
        JSONObject vo =  JSON.parseObject(response.body().string());
        CloverChargesDTO cloverChargesDTO = JSON.toJavaObject(vo,CloverChargesDTO.class);
        //支付失败
        if(StrUtil.isBlank(cloverChargesDTO.getId())){
            log.info("clover card executePayment error : " + vo);
            JSONObject jsonObject = JSON.parseObject(vo.getString("error"));
            return ResponseUtil.fail(jsonObject);
        }

        //创建礼物卡订单
        String cardNumber = RandomUtil.randomNumbers(16);
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setGiftCardId(card.getId());
        order.setCardNumber(cardNumber);
        order.setUserId(userId);
        order.setPayType((byte) 3);
        order.setPayStatus((byte) 2);
        order.setPayTime(LocalDateTime.now());
        order.setAmount(cardBuyCloverGiveeDTO.getAmount());
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setShopId(cardBuyCloverGiveeDTO.getShopId());
        //创建新的用户礼物卡
        LitemallGiftCardUser createCardUser = new LitemallGiftCardUser();
        createCardUser.setCardNumber(cardNumber);
        createCardUser.setEntityCardCode(card.getType()==2?createCardUser.getCardNumber():null);
        createCardUser.setUserId(ObjectUtil.isNotEmpty(giveeUser)?giveeUser.getId():null);
        createCardUser.setUserName(ObjectUtil.isNotEmpty(giveeUser)?giveeUser.getUsername():cardBuyCloverGiveeDTO.getGiveeUser());
        createCardUser.setGiftCardId(card.getId());
        createCardUser.setAmount(cardBuyCloverGiveeDTO.getAmount());
        createCardUser.setStatus(0);
        createCardUser.setDeleted(false);
        //createCardUser.setShopId(cardBuyCloverGiveeDTO.getShopId());
        createCardUser.setIsDefault(0);
        litemallGiftCardUserService.add(createCardUser);

        LitemallGiftCardUserLog log =new LitemallGiftCardUserLog();
        log.setCardNumber(cardNumber);
        log.setType(Constants.LOG_GIFTCARD_SHARE);
        log.setAmount(cardBuyCloverGiveeDTO.getAmount());
        log.setAddUserId(userId);
        log.setContent("clover Purchase gift card purchase gift");
        log.setOrderId(order.getId());
        log.setCardUserId(createCardUser.getUserId());
        log.setBalance(createCardUser.getAmount());
        //log.setShopId(cardBuyCloverGiveeDTO.getShopId());
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        log.setAddUserName(litemallUser.getUsername());
        log.setChangePoints(BigDecimal.ZERO);
        litemallGiftCardUserLogService.add(log);


        long chargesLogId = IdUtil.createSnowflake(1, 1).nextId();
        //保存交易记录
        LumiereCloverChargesLog lumiereCloverChargesLog = LumiereCloverChargesLog.builder()
                .id(chargesLogId)
                .userId(userId)
                .shopId(cardBuyCloverGiveeDTO.getShopId())
                .transactionId(cloverChargesDTO.getId())
                .amount(cloverChargesDTO.getAmount())
                .amountRefunded(cloverChargesDTO.getAmount_refunded())
                .currency(cloverChargesDTO.getCurrency())
                .created(cloverChargesDTO.getCreated())
                .captured(cloverChargesDTO.getCaptured())
                .refNum(cloverChargesDTO.getRef_num())
                .authCode(cloverChargesDTO.getAuth_code())
                .networkStatus(cloverChargesDTO.getOutcome().getNetwork_status())
                .type(cloverChargesDTO.getOutcome().getType())
                .paid(cloverChargesDTO.getPaid())
                .status(cloverChargesDTO.getStatus())
                .customerId(cloverChargesDTO.getSource().getId())
                .addressLine1(cloverChargesDTO.getSource().getAddress_line1())
                .addressLine1Check(cloverChargesDTO.getSource().getAddress_line1_check())
                .addressZip(cloverChargesDTO.getSource().getAddress_zip())
                .addressZipCheck(cloverChargesDTO.getSource().getAddress_zip_check())
                .brand(cloverChargesDTO.getSource().getBrand())
                .expMonth(cloverChargesDTO.getSource().getExp_month())
                .expYear(cloverChargesDTO.getSource().getExp_year())
                .first6(cloverChargesDTO.getSource().getFirst6())
                .last4(cloverChargesDTO.getSource().getLast4())
                .giftCardOrderId(order.getId())
                .transactionType(2)
                .addTime(LocalDateTime.now())
                .deleted(false)
                .build();
        lumiereCloverChargesLogService.save(lumiereCloverChargesLog);
        //赠送用户
        LitemallUser payUser = litemallUserService.findById(userId);
        //分 被赠送用户是否是注册用户
        if(ObjectUtil.isNotEmpty(giveeUser)){
            //用户存在  添加礼物卡购买订单
            order.setAddUserId(giveeUser.getId());
            order.setAddUserName(giveeUser.getUsername());
            litemallGiftCardOrderService.add(order);
            //发送通知信息   给赠送者发送系统通知   被赠送者发送邮箱、短信、系统通知
            wxGiftCardManageService.sendNotificationToExistUser(card,payUser,giveeUser,order,createCardUser,cardBuyCloverGiveeDTO.getMessage());
            //记录日志 1礼物卡订单卡号 4用户礼物卡用户ID 5订单金额 6礼物卡订单ID 7用户礼物卡金额 8礼物卡订单ID
            log(order.getCardNumber(), Constants.LOG_GIFTCARD_PICK, "clover buy gift card to give away",createCardUser.getId(),order.getAmount(),card.getId(),createCardUser.getAmount(),order.getId());
        }else {
            //用户不存在  添加礼物卡购买订单
            order.setAddUserId(null);
            order.setAddUserName(cardBuyCloverGiveeDTO.getGiveeUser());
            litemallGiftCardOrderService.add(order);
            //发送通知信息   给赠送者发送系统通知   被赠送者发送邮箱或短信
            wxGiftCardManageService.sendNotificationToNotExistUser(card,order,createCardUser,payUser,cardBuyCloverGiveeDTO.getGiveeUser(),cardBuyCloverGiveeDTO.getMessage());
            //记录日志 1礼物卡订单卡号 4用户礼物卡用户ID 5订单金额 6礼物卡订单ID 7用户礼物卡金额 8礼物卡订单ID
            log(order.getCardNumber(), Constants.LOG_GIFTCARD_PICK, "clover buy gift card to give away",createCardUser.getId(),order.getAmount(),card.getId(),createCardUser.getAmount(),order.getId());
        }
        return ResponseUtil.ok(createCardUser);
    }
    /**
     * 赠送礼物卡
     *
     * @param userId 用户id
     * @param cardId 卡id
     * @param amount 量
     * @param givee  givee
     * @param shopId 商店id
     * @return {@link Object}
     */
    @Transactional
    public Object buyGiveCard(Integer userId,Integer cardId,BigDecimal amount,String givee, Integer shopId){
        //判断用户登录
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        //判断givee开头是否是1
        if(givee.startsWith(MOBILE_CODE_ONE)){
            //截取账号 ( 去掉第一位字符  )
            givee = givee.substring(1,givee.length());
        }

        if (!RegexUtil.isMobileValid(givee) && !RegexUtil.isEmailExact(givee)) {
            return ResponseUtil.fail(AUTH_INVALID_MOBILE, "手机号或邮箱格式不正确");
        }
        //查看礼物卡是否存在
        LitemallGiftCard card = litemallGiftCardService.findById(cardId);
        if(card == null){
            return ResponseUtil.fail(CARD_INVALID, "礼物卡不存在");
        }
        // 校验礼物卡可购买数量
        Integer saleNum =  (int) litemallGiftCardUserService.sumByCardId(cardId);
        if(card.getNumbers() != 0 && saleNum >= card.getNumbers()){
            return ResponseUtil.fail(CARD_SALED_OVER,"礼物卡已售罄");
        }
        //是否是注册用户
        LitemallUser giveeUser = litemallUserService.queryMobileOrEmail(givee);


        //创建一个礼物卡的预支付订单
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setGiftCardId(card.getId());
        //order.setCardNumber(RandomUtils.generateRandomStr(10));
        order.setUserId(userId);
        order.setPayType(Constants.PAY_TYPE_PAYPAL);
        order.setPayStatus(Constants.PAY_STATUS_DOING);
        order.setPayTime(LocalDateTime.now());
        order.setAmount(amount);
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setUpdateTime(LocalDateTime.now());
        order.setShopId(shopId);
        order.setAddUserId(ObjectUtil.isNotNull(giveeUser)?giveeUser.getId():null);
        //预支付的用户名  || 如果用户未注册则注册时一定要使用当前被赠送账号
        order.setAddUserName(ObjectUtil.isNotNull(giveeUser)?giveeUser.getUsername():givee);
        litemallGiftCardOrderService.add(order);
        return ResponseUtil.ok(order);
    }

    /**
     * 付款准备
     * @param orderId
     * @param userId
     * @return
     */
    public Object getPayment(Integer orderId, Integer userId,String userName,Integer shopId,String message) {
        String sUrl = successUrl+"?userName="+userName+"&shopId="+shopId;
        return cardPaypalService.getPayment(userId, orderId, sUrl, cancelUrl,message);
    }

    /**
     * 付款完成
     * @param paymentId
     * @param payerId
     * @return
     */
    public Object executePayment(String paymentId, String payerId) {
        try {
            return cardPaypalService.executePayment(paymentId, payerId);
        }catch (Exception e){
            //支付异常，退款
            cardPaypalService.refund(paymentId, payerId);
            return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, "支付失败");
        }
    }


    /**
     * 退款
     * @param orderId
     * @return
     */
    public Object refund(Integer orderId, Integer userId) {
        LitemallGiftCardOrder orderServiceById = litemallGiftCardOrderService.findById(orderId);
        if(orderServiceById == null){
            return ResponseUtil.fail(PaymentResponseCode.ORDER_UNKNOWN, "订单不存在");
        }
        if(orderServiceById.getUserId() != userId){
            return ResponseUtil.fail(PaymentResponseCode.ORDER_UNKNOWN, "订单不存在");
        }
//        if(cardPaypalService.refund(orderId)){
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setId(orderId);
//            order.set
        order.setPayStatus(Constants.PAY_STATUS_REFUSE);
        litemallGiftCardOrderService.update(order);
        return orderId;
//        }
//        return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, "退款失败");
    }


    /**
     * 分享
     * @param dto
     * @return
     */
    public Object share(CardShareDTO dto, Integer userId) {
        LitemallGiftCardUser card = litemallGiftCardUserService.findByNumber(dto.getCardNumber());
        if(card == null){
            return ResponseUtil.fail(WxResponseCode.CARD_INVALID, "礼物卡不存在");
        }
        //已经分享
        if(litemallGiftCardShareService.findByCardNumber(dto.getCardNumber()) != null){
            return ResponseUtil.ok(litemallGiftCardShareService.findByCardNumber(dto.getCardNumber()));
        }
        LitemallGiftCardShare share = new LitemallGiftCardShare();
        share.setCardNumber(dto.getCardNumber());
        share.setCode(StringUtils.isNotBlank(dto.getCode())?dto.getCode(): GeneratorUtil.codeGenerator());
        if(dto.getActiveTime() != null){
            DateTimeFormatter timeDtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            share.setActiveTime(LocalDateTime.of(LocalDate.parse(dto.getActiveTime(), timeDtf), LocalTime.MIN));
        }
        share.setLink(GeneratorUtil.linkGenerator());
        share.setUserId(userId);
        share.setBlessing(dto.getBlessing());
        litemallGiftCardShareService.add(share);
        log(share.getCardNumber(), Constants.LOG_GIFTCARD_SHARE, "分享礼物卡",userId,card.getId(),card.getAmount(),null);

        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER," card share", "Gift card"+share.getCardNumber()+"Share success ", userId, share);

        return ResponseUtil.ok(share);
    }

    /**
     * 取消分享
     * @param shareCardId
     * @param userId
     * @return
     */
    public Object shareCancel(Integer shareCardId, Integer userId) {
        LitemallGiftCardShare shareCard = litemallGiftCardShareService.findById(shareCardId);
        LitemallGiftCardUser card = null;
        if(shareCard.getCardNumber() != null){
            card = litemallGiftCardUserService.findByNumber(shareCard.getCardNumber());
        }
        if(shareCard == null || shareCard.getUserId() != userId){
            return ResponseUtil.fail(WxResponseCode.GIFT_CARD_SHARE_NOT_AUTH, "礼物卡不存在");
        }
        shareCard.setDeleted(true);
        shareCard.setActiveTime(LocalDateTime.now());
        litemallGiftCardShareService.update(shareCard);
        log(shareCard.getCardNumber(), Constants.LOG_GIFTCARD_SHARE, "取消分享礼物卡",userId,card.getId(),card.getAmount(),null);
        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"card canceld sharing", "Gift card"+shareCard.getCardNumber()+"cancel sharing", userId, shareCard);
        return ResponseUtil.ok(shareCard);
    }

    /**
     * 根据link查找分享的礼物卡
     * @param link
     * @return
     */
    public Object find(String link) {
        LitemallGiftCardShare share = litemallGiftCardShareService.findByLink(link);
        if(share == null){
            return ResponseUtil.fail(WxResponseCode.GIFT_CARD_SHARE_NOT_EXIST, "分享不存在");
        }
        if(share.getActiveTime() != null && share.getActiveTime().compareTo(LocalDateTime.now()) == -1){
            return ResponseUtil.fail(WxResponseCode.GIFT_CARD_SHARE_NOT_EXIST, "分享不存在");
        }
        LitemallGiftCardUser cardUser = litemallGiftCardUserService.findByNumber(share.getCardNumber());
        LitemallGiftCard card = litemallGiftCardService.findById(cardUser.getGiftCardId());
        cardUser.setUserId(null);
        cardUser.setCardNumber(null);
        Map map = new HashMap();
        map.put("user", cardUser);
        map.put("card",card);
        return ResponseUtil.ok(map);
    }

    /**
     * 领取礼物卡
     * @param link
     * @return
     */
    @Transactional
    public Object pick(String link, String code, Integer userId) {
        LitemallGiftCardShare share = litemallGiftCardShareService.findByCodeAndLink(link, code);
        if(share == null){
            return ResponseUtil.fail(WxResponseCode.GIFT_CARD_SHARE_NOT_EXIST, "分享不存在");
        }
        if(share.getActiveTime() != null && share.getActiveTime().compareTo(LocalDateTime.now()) == -1){
            return ResponseUtil.fail(WxResponseCode.GIFT_CARD_SHARE_NOT_EXIST, "分享不存在");
        }
        LitemallGiftCardUser cardUser = litemallGiftCardUserService.findByNumber(share.getCardNumber());

        //修改礼物卡所属
        LitemallGiftCardUser update = new LitemallGiftCardUser();
        update.setId(cardUser.getId());
        update.setUpdateTime(cardUser.getUpdateTime());
        update.setUserId(userId);
        LitemallUser user = litemallUserService.findById(userId);
        if(StringUtils.isNotEmpty(user.getUsername())){
            update.setUserName(user.getUsername());
        }
        if(litemallGiftCardUserService.updateById2(update) == 0){
            return ResponseUtil.fail(WxResponseCode.GIFT_CARD_SHARE_PICKED, "礼物卡已被领取");
        }
        //删除礼物卡分享
        litemallGiftCardShareService.deleteById(share.getId());
        //发送消息给赠送者
//        notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED, new String[]{order.getOrderSn().substring(8, 14)});

        log(share.getCardNumber(), Constants.LOG_GIFTCARD_PICK, "领取礼物卡",userId,update.getId(),cardUser.getAmount(),null);

        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"card received", "card"+share.getCardNumber()+"had been recieved", share.getUserId(),share);
        return ResponseUtil.ok(cardUser);
    }


    /**
     * 我的礼物卡列表
     * @param userId
     * @return
     */
    public Object myCards(Integer userId) {
        List<MyCardVo> cards = CollUtil.newArrayList();
        //根据userID找到礼物卡
        List<LitemallGiftCardUser> litemallGiftCardUsers = litemallGiftCardUserService.list(Wrappers.lambdaQuery(LitemallGiftCardUser.class).eq(LitemallGiftCardUser::getUserId, userId));
        //组装OV
        litemallGiftCardUsers.stream().map(item->{
            if(StringUtils.isNotEmpty(item.getCardNumber())){
                LitemallGiftCard giftCard = litemallGiftCardService.findById(item.getGiftCardId());
                MyCardVo vo = MyCardVo.builder()
                        .amount(item.getAmount().setScale(2))
                        .name(giftCard.getName())
                        .cardNumber(item.getCardNumber())
                        .picUrl(giftCard.getPicUrl())
                        .id(item.getId())
                        .shareDetail(litemallGiftCardShareService.findByCardNumber(item.getCardNumber()))
                        .isDefault(item.getIsDefault())
                        .type(giftCard.getType())
                        .build();
                cards.add(vo);
            }
            return cards;
        }).collect(Collectors.toList());
        //将默认的礼物卡放在第一
        for (int i = 0; i < cards.size(); i++) {
            if(cards.get(i).getIsDefault()==1){
                //第一个礼物卡
                MyCardVo firstCard = cards.get(0);
                //默认的礼物卡
                MyCardVo defaultCard = cards.get(i);
                //交换位置
                cards.set(0,defaultCard);
                cards.set(i,firstCard);
            }
        }
        return ResponseUtil.ok(cards);
    }

    /**
     * 创建或更新卡片
     * 付款成功后创建卡或者更新卡上余额
     *
     * @param userId    用户id
     * @param paymentId 支付id
     * @param userName  用户名
     */
    @Transactional
    public void createOrUpdateCard(Integer userId, String paymentId,String userName) {
        LitemallGiftCardOrder order = litemallGiftCardOrderService.findByOutTradeNo(paymentId);
        //添加优惠券
        List<LumiereCouponStrategy> couponStrategies = lumiereCouponStrategyService.list(Wrappers.lambdaQuery(LumiereCouponStrategy.class)
                .eq(LumiereCouponStrategy::getCouponType,8)
                .eq(LumiereCouponStrategy::getStatus, 1)
                .le(LumiereCouponStrategy::getRechargeAmount,order.getAmount()));
        if(couponStrategies!=null&&couponStrategies.size()>0) {
            for (LumiereCouponStrategy lumiereCouponStrategy : couponStrategies) {
                long nextId = IdUtil.getSnowflake(2, 2).nextId();
                LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(lumiereCouponStrategy);
                //发放券
                for (int i = 1;i<=lumiereCouponStrategy.getTotal();i++){
                    LumiereCouponUser coupon = LumiereCouponUser.builder()
                            .userId(userId)
                            .strategyId(lumiereCouponStrategy.getId())
                            .couponId(lumiereCouponStrategy.getCouponId())
                            .userName(userName)
                            .startTime(localDateTimes[0])
                            .endTime(localDateTimes[1])
                            .code(String.valueOf(nextId))
                            .addTime(LocalDateTime.now())
                            .updateTime(LocalDateTime.now())
                            .deleted(false)
                            .build();
                    lumiereCouponUserService.save(coupon);
                }
            }
        }
        //只创建了礼物卡订单，没有创建礼物卡用户表
        if(StringUtils.isEmpty(order.getCardNumber())){
            try{
                //添加用户礼物卡
                LitemallGiftCardUser card = new LitemallGiftCardUser();
                card.setAmount(order.getAmount());
                card.setGiftCardId(order.getGiftCardId());
                //使用hutool包全局生成ID
                card.setCardNumber(RandomUtil.randomNumbers(16));
                card.setStatus(1);
                card.setIsDefault(0);
                //card.setShopId(order != null ? order.getShopId() : null);
                //礼物卡
                LitemallGiftCard g = litemallGiftCardService.findById(order.getGiftCardId());
                //赠送者
                LitemallUser beGiftUser = litemallUserService.findById(order.getUserId());
                if(StrUtil.isNotBlank(order.getAddUserName())?ObjectUtil.isNotNull(litemallUserService.queryMobileOrEmail(order.getAddUserName())):false){
                    LitemallUser giftUser = litemallUserService.queryMobileOrEmail(order.getAddUserName());
                    //补缺用户礼物卡信息
                    card.setUserName(giftUser.getUsername());
                    card.setUserId(giftUser.getId());
                    //赠送给有账号的用户
                    wxGiftCardManageService.sendNotificationToExistUser(g,beGiftUser,giftUser,order,card,order.getMessage());
                    //记录日志
                    log(order.getCardNumber(), Constants.LOG_GIFTCARD_SHARE, "PayPal赠送礼物卡",card.getUserId(),order.getAmount(),card.getId(),card.getAmount(),order.getId());
                }else if(StrUtil.isNotBlank(order.getAddUserName())?ObjectUtil.isEmpty(litemallUserService.queryMobileOrEmail(order.getAddUserName())):false){
                    card.setUserId(null);
                    card.setUserName(order.getAddUserName());
                    //赠送给没有账号的用户
                    wxGiftCardManageService.sendNotificationToNotExistUser(g,order,card,beGiftUser,order.getAddUserName(),order.getMessage());
                    //记录日志
                    log(order.getCardNumber(), Constants.LOG_GIFTCARD_SHARE, "PayPal赠送礼物卡",card.getUserId(),order.getAmount(),card.getId(),card.getAmount(),order.getId());
                }else{

                    //给自己买卡
                    String zcontent = "Congratulations, you got the " + g.getName();
                    log(order.getCardNumber(), Constants.LOG_GIFTCARD_RECHARGE, "PayPal自己购买礼物卡",card.getUserId(),order.getAmount(),card.getId(),card.getAmount(),order.getId());
                    noticeHelper.noticeUser( Constants.MSG_TYPE_OTHER,"Gift card recharge", zcontent, order.getUserId(),card);
                    awsNotifyService.sendSms(MOBILE_CODE_ONE+beGiftUser.getMobile(), zcontent,Constants.AWS_MESSAGE_TYPE_PROMOTIONAL);
                    //补缺用户礼物卡信息
                    card.setUserId(order.getAddUserId());
                    card.setUserName(order.getAddUserName());

                    //充值记录
                    litemallRechargeTransactionsService.save(new LitemallRechargeTransactions()
                            .setUserId(beGiftUser.getId())
                            .setCardNo(card.getCardNumber())
                            .setUsername(beGiftUser.getUsername())
                            .setRechargeType(Constants.RECHARGE_TYPE_GIFT_CARD)
                            .setPayType(Constants.PAY_TYPE_PAYPAL)
                            .setRechargeAmount(order.getAmount())
                            .setRechargeSource(Constants.ORDER_SOURCE_APP)
                    );
                }
                //插入用户礼物卡
                litemallGiftCardUserService.add(card);
                //修改订单的cardNumber  给礼物卡订单添加上卡号
                LitemallGiftCardOrder update = new LitemallGiftCardOrder();
                update.setId(order.getId());
                update.setCardNumber(card.getCardNumber());
                litemallGiftCardOrderService.update(update);

            }catch (Exception e){
                logger.info("Exception in createCard:"+ e.getMessage());
                //当cardNumber冲突时重新插入
                createOrUpdateCard(userId, paymentId,userName);
            }
            //修改卡余额
        }else{
            //充值礼物卡
            LitemallGiftCardUser card = litemallGiftCardUserService.findByNumber(order.getCardNumber());
            card.setAmount(card.getAmount().add(order.getAmount()));
            litemallGiftCardUserService.updateWithOptimisticLocker(card, card.getUpdateTime());
            log(order.getCardNumber(), Constants.LOG_GIFTCARD_RECHARGE, "充值"+order.getAmount(),userId,card.getId(),card.getAmount(),order.getId());
            LitemallUser user = litemallUserService.findById(card.getUserId());

            //充值记录
            litemallRechargeTransactionsService.save(new LitemallRechargeTransactions()
                    .setUserId(user.getId())
                    .setCardNo(card.getCardNumber())
                    .setUsername(user.getUsername())
                    .setRechargeType(Constants.RECHARGE_TYPE_GIFT_CARD)
                    .setPayType(Constants.PAY_TYPE_PAYPAL)
                    .setRechargeAmount(order.getAmount())
                    .setRechargeSource(Constants.ORDER_SOURCE_APP)
            );

            //调用充值策略
            List<LumiereCouponStrategy> couponStrategyList = lumiereCouponStrategyService.list(Wrappers.lambdaQuery(LumiereCouponStrategy.class)
                    .eq(LumiereCouponStrategy::getCouponType, 8)
                    .eq(LumiereCouponStrategy::getStatus, 1));
            couponStrategyList.stream().forEach(couponStrategy -> {
                if(couponStrategy.getRechargeAmount().compareTo(order.getAmount())!=-1){
                    //赠送券
                    long nextId = IdUtil.getSnowflake(2, 2).nextId();
                    LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(couponStrategy);
                    LumiereCouponUser couponUser = LumiereCouponUser.builder()
                            .userId(userId)
                            .strategyId(couponStrategy.getId())
                            .couponId(couponStrategy.getCouponId())
                            .startTime(localDateTimes[0])
                            .endTime(localDateTimes[1])
                            .userName(user.getUsername())
                            .code(String.valueOf(nextId))
                            .addTime(LocalDateTime.now())
                            .updateTime(LocalDateTime.now())
                            .deleted(false)
                            .build();
                    lumiereCouponUserService.save(couponUser);
                    noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER, LitemallWXConstants.WX_GIFT_RECHARGE_USER_TITLE_NOTICEMAIL,
                            String.format(LitemallWXConstants.WX_GIFT_RECHARGE_USER_NOTICEMAIL,userName,order.getAmount()), userId, order);
                }
            });
        }

        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"Gift card payment", "Gift card recharge succeeded", userId, order);
    }



    /**
     * 礼物卡充值
     * @param userId
     * @param cardNumber
     * @param amount
     * @return
     */
    public Object recharge(Integer userId, String cardNumber, BigDecimal amount,Integer shopId) {
        LitemallGiftCardUser card = litemallGiftCardUserService.findByNumber(cardNumber);
        if(card != null){
            if(!userId.equals(card.getUserId())){
                return ResponseUtil.fail(WxResponseCode.CARD_INVALID, "用户礼物卡不存在");
            }
        }else{
            return ResponseUtil.fail(CARD_INVALID,"礼物卡不存在");
        }
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setAmount(amount);
        order.setUserId(userId);
        order.setCardNumber(cardNumber);
        order.setPayStatus(Constants.PAY_STATUS_DOING);
        order.setGiftCardId(card.getGiftCardId());
        order.setShopId(shopId);
        order.setAddUserId(userId);
        litemallGiftCardOrderService.add(order);
        return ResponseUtil.ok(order);
    }

    /**
     * 余额充值礼物卡
     *
     * @param userId     用户id
     * @param cardNumber 卡号
     * @param amount     量
     * @param shopId     商店id
     * @return {@link ResponseUtil.Response}
     */
    @Transactional
    public ResponseUtil.Response balanceRecharge(Integer userId, String cardNumber, BigDecimal amount, Integer shopId) {
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        LitemallUser user = litemallUserService.findById(userId);
        if(StrUtil.isEmpty(cardNumber)){
            return ResponseUtil.badArgument();
        }
        if(amount == null||amount.compareTo(new BigDecimal(0.00))<0){
            return ResponseUtil.badArgument();
        }
        //判断礼物卡效果
        LitemallGiftCardUser card = litemallGiftCardUserService.getOne(Wrappers.lambdaQuery(LitemallGiftCardUser.class)
                .eq(LitemallGiftCardUser::getUserId,userId)
                .eq(LitemallGiftCardUser::getCardNumber,cardNumber));
        if(card != null){
            if(!userId.equals(card.getUserId())){
                return ResponseUtil.fail(WxResponseCode.CARD_INVALID, "用户礼物卡不存在");
            }
        }else{
            return ResponseUtil.fail(CARD_INVALID,"礼物卡不存在");
        }

        //创建礼物卡订单
        LitemallGiftCardOrder order = new LitemallGiftCardOrder();
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setAmount(amount);
        order.setUserId(userId);
        order.setCardNumber(card.getCardNumber());
        order.setGiftCardId(card.getGiftCardId());
        order.setShopId(shopId);
        order.setAddUserId(userId);
        order.setPayType(Constants.ORDER_PAY_TYPE_BALANCE);
        order.setPayStatus((byte) 2);
        order.setPayTime(LocalDateTime.now());
        litemallGiftCardOrderService.add(order);

        //创建消费记录
        LitemallRechargeConsumption rechargeConsumption = new LitemallRechargeConsumption();
        rechargeConsumption.setUserId(user.getId());
        rechargeConsumption.setOrderId(order.getId());
        rechargeConsumption.setMobile(StrUtil.isNotEmpty(user.getMobile())?user.getMobile():null);
        rechargeConsumption.setUsername(user.getUsername());
        rechargeConsumption.setUserLevel(user.getUserLevel());
        rechargeConsumption.setAvailableAmount(user.getAvailableAmount());
        rechargeConsumption.setPoints(user.getPoints());
        rechargeConsumption.setType((byte) 2);
        rechargeConsumption.setAmount(amount);
        rechargeConsumption.setDeleted(false);
        rechargeConsumption.setAddUserId(userId);
        rechargeConsumption.setOrderSource((byte) 1);
        litemallRechargeConsumptionService.add(rechargeConsumption);

        //查余额
        LitemallUser currentUser = litemallUserService.findById(userId);
        if(currentUser.getAvailableAmount().compareTo(amount)==-1){
            return ResponseUtil.fail(MONEY_BUY_PAY_INSUFFICIENT,"用户余额不足");
        }
        //扣减余额
        currentUser.setAvailableAmount(currentUser.getAvailableAmount().subtract(amount));
        if(!litemallUserService.updateById(currentUser)){
            return ResponseUtil.fail(MONEY_DEDUCT_FAILURE,"余额扣除失败！");
        }
        //充值礼物卡
        card.setAmount(card.getAmount().add(order.getAmount()));
        litemallGiftCardUserService.updateWithOptimisticLocker(card, card.getUpdateTime());

        //添加优惠券
        List<LumiereCouponStrategy> couponStrategies = lumiereCouponStrategyService.list(Wrappers.lambdaQuery(LumiereCouponStrategy.class)
                .eq(LumiereCouponStrategy::getCouponType,8)
                .eq(LumiereCouponStrategy::getStatus, 1)
                .eq(LumiereCouponStrategy::getRechargeAmount,amount));
        if(couponStrategies!=null&&couponStrategies.size()>0) {
            for (LumiereCouponStrategy lumiereCouponStrategy : couponStrategies) {
                long nextId = IdUtil.getSnowflake(2, 2).nextId();
                LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(lumiereCouponStrategy);
                //发放券
                for (int i = 1;i<=lumiereCouponStrategy.getTotal();i++){
                    LumiereCouponUser coupon = LumiereCouponUser.builder()
                            .userId(userId)
                            .strategyId(lumiereCouponStrategy.getId())
                            .couponId(lumiereCouponStrategy.getCouponId())
                            .userName(user.getUsername())
                            .startTime(localDateTimes[0])
                            .endTime(localDateTimes[1])
                            .code(String.valueOf(nextId))
                            .addTime(LocalDateTime.now())
                            .updateTime(LocalDateTime.now())
                            .deleted(false)
                            .build();
                    lumiereCouponUserService.save(coupon);
                }
            }
        }

        log(cardNumber, Constants.LOG_GIFTCARD_RECHARGE, "balanceRecharge"+order.getAmount(), userId, order.getAmount(), order.getId(),card.getId(),card.getAmount());
        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"Gift card payment", "Gift card recharge succeeded", userId, order);
        return ResponseUtil.ok(card.getCardNumber());
    }



    /**
     * 我的分享
     * @param userId
     * @return
     */
    public Object myShares(Integer userId) {
        List<Map> rtn = new ArrayList<>();
        List<LitemallGiftCardShare> shares = litemallGiftCardShareService.findByUserId(userId);
        for(LitemallGiftCardShare share: shares){
            LitemallGiftCardUser cardUser = litemallGiftCardUserService.findByNumber(share.getCardNumber());
            LitemallGiftCard card = litemallGiftCardService.findById(cardUser.getGiftCardId());
            Map map = new HashMap();
            map.put("share", share);
            map.put("card",card);
            rtn.add(map);
        }
        return ResponseUtil.ok(rtn);
    }

    /**
     * 记录日志(充值、消费、赠送、领取、销毁)
     * @param cardNumber
     * @param type
     * @param content
     * @param userId
     */
    public void log(String cardNumber, Byte type, String content, Integer userId,Integer cardUserId,BigDecimal balance,Integer orderId){
        log(cardNumber,type,content,userId,null,cardUserId,balance,orderId);
    }
    public void log(String cardNumber, Byte type, String content, Integer userId, BigDecimal amount,Integer cardUserId,BigDecimal balance,Integer orderId){
        log(cardNumber,type,content,userId,amount, orderId,cardUserId,balance);
    }

    public void log(String cardNumber, Byte type, String content, Integer userId, BigDecimal amount, Integer orderId,Integer cardUserId,BigDecimal balance){
        LitemallUser user = litemallUserService.findById(userId);
        LitemallGiftCardUserLog log = new LitemallGiftCardUserLog();
        log.setCardNumber(cardNumber);
        log.setType(type);
        if(userId == null && orderId != null){
            LitemallGiftCardOrder order = litemallGiftCardOrderService.findById(orderId);
            userId =  order.getUserId() != null ? order.getUserId() : null;
            amount = amount == null ? order.getAmount() : amount;
            log.setShopId(order != null ? order.getShopId() : null);
        }
        log.setAddUserId(userId);
        log.setContent(content);
        log.setAmount(amount);
        log.setOrderId(orderId);
        log.setCardUserId(cardUserId);
        log.setBalance(balance);
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        if(user != null){
            log.setContent(user.getUsername() + ":" + content);
            log.setAddUserName(user.getUsername());
        }
        log.setChangePoints(BigDecimal.ZERO);
        litemallGiftCardUserLogService.add(log);
    }

    /**
     * 获取card充值消费记录，不包括之前用户的记录
     * @param userId
     * @param cardNumber
     * @param page
     * @param limit
     * @param sort
     * @param order
     * @return
     */
    public Object  bill(Integer userId, String cardNumber, Integer page, Integer limit, String sort, String order) {
        List<Byte> types = new ArrayList<>(Arrays.asList(new Byte[]{Constants.LOG_GIFTCARD_RECHARGE,Constants.LOG_GIFTCARD_CONSUME,Constants.LOG_GIFTCARD_TRANSTER_OUT,Constants.LOG_GIFTCARD_TRANSTER_IN,Constants.LOG_GIFTCARD_REFUND}));
        List<LitemallGiftCardUserLog> logs = litemallGiftCardUserLogService.querySelective(types,userId, cardNumber, page, limit, sort, order);
        List<LitemallGiftCardUserLogVo> vos  =  logs.stream().map(log -> {
            LitemallGiftCardUserLogVo vo = new LitemallGiftCardUserLogVo();
            BeanUtils.copyProperties(log,vo);
            //根据orderId 查询订单商品
            if(log.getOrderId() != null){
                List<LitemallOrderGoods> orderGoods =  orderGoodsService.queryByOid(log.getOrderId());
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < orderGoods.size(); i++) {
                    sb.append(orderGoods.get(i).getGoodsName());

                    if(i != orderGoods.size() - 1){
                        sb.append(",");
                    }
                }

                vo.setGoodsName(sb.toString());
                sb = null;
            }else{
                vo.setGoodsName("");
            }

            vo.setOrderId(vo.getOrderId() == null ? 0 : vo.getOrderId());

            if(vo.getBalance() != null){
                vo.setBalance(vo.getBalance().setScale(2));
            }

            if(vo.getAmount() != null){
                vo.setAmount(vo.getAmount().setScale(2));
            }

            return  vo;
        }).collect(Collectors.toList());

        return ResponseUtil.okList(vos);
    }

    /**
     * 修改分享祝福语
     * @param dto
     * @param userId
     * @return
     */
    public Object updateShare(CardShareDTO dto, Integer userId) {
        LitemallGiftCardShare share = new LitemallGiftCardShare();
        share.setBlessing(dto.getBlessing());
        share.setId(dto.getId());
        share.setUserId(userId);
        litemallGiftCardShareService.update(share);
        return ResponseUtil.ok(dto);
    }

    /**
     * 默认礼物卡
     * @param userId
     * @param cardUserId
     * @return
     */
    public Object changeDefaultCard(Integer userId,Integer cardUserId){
        List<LitemallGiftCardUser> cardUsers =  litemallGiftCardUserService.findCardByUserId(userId);
        cardUsers.stream().forEach(user -> {
            if(user.getId().equals(cardUserId)){
                if(user.getIsDefault().equals(Constants.GIFT_CARD_USER_IS_NOT_DEFAULT)){
                    user.setIsDefault(Constants.GIFT_CARD_USER_IS_DEFAULT);
                    litemallGiftCardUserService.updateDefaultById(user);
                    //改变其他礼物卡为不默认
                    cardUsers.stream().forEach(cardUser -> {
                        if(!cardUser.getId().equals(cardUserId)) {
                            cardUser.setIsDefault(Constants.GIFT_CARD_USER_IS_NOT_DEFAULT);
                            litemallGiftCardUserService.updateDefaultById(cardUser);
                        }
                    });
                }else{
                    user.setIsDefault(Constants.GIFT_CARD_USER_IS_NOT_DEFAULT);
                    litemallGiftCardUserService.updateDefaultById(user);
                }
//               litemallGiftCardUserService.updateById(user);
            }
        });


        return ResponseUtil.ok("修改默认礼物卡成功");
    }

    /**
     * 绑定实体卡
     * @param userId
     * @param cardNumber
     * @param password
     * @return
     */
    public Object bind(Integer userId,String cardNumber,String password){
        LitemallUser user =  litemallUserService.findById(userId);

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(password, user.getPassword())) {
            return ResponseUtil.fail(AUTH_INVALID_ACCOUNT, "账号密码不对");
        }

        //通过卡号查询是否已经被绑定
        LitemallGiftCardUser cardUser = litemallGiftCardUserService.findByNumber(cardNumber);

        if(cardUser == null){
            return ResponseUtil.fail(WxResponseCode.CARD_INVALID,"礼物卡不存在");
        }else{
            if(cardUser.getEntityCardCode() == null){
                cardUser.setEntityCardCode(cardNumber);
                cardUser.setUserId(userId);
                cardUser.setUserName(user != null ? user.getUsername() : null);
                cardUser.setBindTime(LocalDateTime.now());
                litemallGiftCardUserService.updateById(cardUser);
            }else{
                if(cardUser.getEntityCardCode().equals(cardNumber)== true){
                    return ResponseUtil.fail(WxResponseCode.CARD_HAS,"礼物卡已存在");
                }else{
                    return ResponseUtil.fail(CARD_HAD_BEEN_BIND,"礼物卡已绑定别的账号");
                }
            }
        }
        return ResponseUtil.ok("绑定成功");
    }

    /**
     * 转出
     * @param userId
     * @param cardUserId
     * @return
     */
    public Object transferOut(Integer userId,Integer cardUserId,Integer givenCardUserId,BigDecimal amount){
        LitemallGiftCardUser user = litemallGiftCardUserService.findById(cardUserId);
        LitemallGiftCardUser givenUser = litemallGiftCardUserService.findById(givenCardUserId);
        if(user != null){
            if(user.getAmount() != null && user.getAmount().compareTo(amount) >= 0){
                user.setAmount(user.getAmount().subtract(amount));
                if(givenUser == null){
                    return ResponseUtil.fail(WxResponseCode.CARD_INVALID,"礼物卡不存在");
                }else{
                    givenUser.setAmount(givenUser.getAmount().add(amount));
                }

            }else{
                return ResponseUtil.fail(CARD_AVALIABLE_AMOUNT_NOT_ENOUGH,"礼物卡余额不足");
            }
        }else{
            return ResponseUtil.fail(WxResponseCode.CARD_INVALID,"礼物卡不存在");
        }

        litemallGiftCardUserService.updateById(user);
        litemallGiftCardUserService.updateById(givenUser);

        //记录日志到Log
        log(user.getCardNumber(), Constants.LOG_GIFTCARD_TRANSTER_OUT, "转出至"+givenUser.getCardNumber(),userId,amount,null,user.getId(),user.getAmount());
        log(givenUser.getCardNumber(), Constants.LOG_GIFTCARD_TRANSTER_IN, "转入自"+user.getCardNumber(),userId,amount,null,givenUser.getId(),givenUser.getAmount());
        return ResponseUtil.ok("转出成功");
    }

    public Object exceptCurrentCard(Integer userId,Integer cardUserId){
        List<LitemallGiftCardUser> users = litemallGiftCardUserService.findCardByUserId(userId);
        users = users.stream().filter(user ->{
            if(user.getId() != cardUserId){
                return true;
            }else{
                return false;
            }
        }).collect(Collectors.toList());
        return ResponseUtil.okList(users);
    }

    /**
     * 删除礼物卡
     * @param cardUserId
     * @return
     */
    public Object delete(Integer cardUserId){
        LitemallGiftCardUser user = litemallGiftCardUserService.findById(cardUserId);
        if(user.getAmount().compareTo(BigDecimal.ZERO) > 0){
            return ResponseUtil.fail(222,"礼物卡还有余额，不能删除礼物卡");
        }
        litemallGiftCardUserService.deleteById(cardUserId);
        return ResponseUtil.ok("删除礼物卡成功");
    }

    /**
     * 查询可用的虚拟礼物卡
     * @param userId
     * @return
     */
    public Object myVirtualCard(Integer userId){
        List<LitemallGiftCardUser> giftCardUsers =   litemallGiftCardUserService.findCardByUserId(userId);

        giftCardUsers = giftCardUsers.stream().filter( cardUser ->{
            if(cardUser.getGiftCardId() == null){
                return false;
            }

            LitemallGiftCard giftCard =  litemallGiftCardService.findById(cardUser.getGiftCardId());

            if(giftCard.getType() != null && giftCard.getType() == 1){
                return true;
            }else{
                return false;
            }
        }).collect(Collectors.toList());

        return ResponseUtil.okList(giftCardUsers);
    }

    public Object giftCardUserDetail(Integer cardUserId){
        LitemallGiftCardUser user = litemallGiftCardUserService.findById(cardUserId);
        if(ObjectUtil.isNull(user)){
            return ResponseUtil.fail(CARD_USER_INVALID,"礼物卡用户不存在");
        }
        LitemallGiftCard card = new LitemallGiftCard();
        if(user.getGiftCardId() != null){
            card = litemallGiftCardService.findById(user.getGiftCardId());
        }
        GiftCardUserVo vo = GiftCardUserVo.builder()
                .amount(user.getAmount().setScale(2))
                .cardNumber(user.getCardNumber())
                .cardUserId(user.getId())
                .name(card.getName())
                .type(card.getType())
                .isDefault(user.getIsDefault())
                .picture(card.getPicUrl())
                .build();
        return ResponseUtil.ok(vo);
    }

    @Transactional
    public LitemallRechargeConsumption saveLog(BigDecimal actualPrice, LitemallUser user, Byte type,Integer giftCardId){
        LitemallRechargeConsumption log = new LitemallRechargeConsumption();
        log.setAmount(actualPrice);
        log.setAddUserId(user.getId());
        log.setUserId(user.getId());
        log.setUsername(user.getUsername());
        log.setMobile(user.getMobile());
        log.setPoints(user.getPoints());
        log.setType(type);
        log.setUserLevel(user.getUserLevel());
        log.setOrderId(giftCardId);
        log.setAvailableAmount(user.getAvailableAmount().subtract(actualPrice));
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        litemallRechargeConsumptionService.add(log);
        return log;
    }


    public ResponseUtil.Response balanceRechargeByClover(Integer userId, Integer shopId, String cardNumber, BigDecimal amount, String token) {
        return giftCardCloverService.executePayment(userId,shopId,cardNumber,amount,token);
    }



}
